﻿using BaiduBce.Services.Bos.Model;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using LimaLims.Application.Service.Base.Dto;
using LimaLims.Application.Service.Basic.Dto;
using LimaLims.Application.Service.Sys;
using LimaLims.Core;
using LimaLims.Core.Entity.Basic;
using LimaLims.Core.Entity.TestCenter;
using LimaLims.Core.Enum;
using LimaLims.Core.Util;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using System.Reflection;
using Yitter.IdGenerator;

namespace LimaLims.Application.Service.Basic
{
    /// <summary>
    /// 试验方案服务
    /// </summary>
    [ApiDescriptionSettings(Name = "InspectionScheme", Order = 154)]
    [Route("api")]
    public class InspectionSchemeService : IInspectionSchemeService, IDynamicApiController, ITransient
    {
        private readonly IRepository<InspectionScheme> _inspectionSchemeRep;  // 设备仪器表仓储
        private readonly IRepository<ExperimentPlan> _experimentPlanRep;  // 试验计划
        private readonly IRepository<InspectionData> _inspectionDataRep;  // 设备仪器表仓储
        private readonly IGenerateCodeUtilService _generateCodeUtilService;//编码规则
        public InspectionSchemeService(IRepository<InspectionScheme> inspectionSchemeRep, IRepository<InspectionData> inspectionDataRep, IGenerateCodeUtilService generateCode, IRepository<ExperimentPlan> experimentPlanRep)
        {
            _inspectionSchemeRep = inspectionSchemeRep;
            _inspectionDataRep = inspectionDataRep;
            _generateCodeUtilService = generateCode;
            _experimentPlanRep = experimentPlanRep;
        }

        private async Task UpdateInspectionSchemeData(AddInspectionSchemeInput input, InspectionScheme inspectionScheme)
        {
            if (input.InspectionDatas == null || input.InspectionDatas.Count < 1)
                return;

            var oldData = await _inspectionDataRep.DetachedEntities.Where(u => u.InspectionSchemeId == input.Id).ToListAsync();

            if (oldData.Count > 0)
            {
                await _inspectionDataRep.DeleteAsync(oldData);
            }

            List<InspectionData> items = new List<InspectionData>();

            foreach (var item in input.InspectionDatas)
            {
                var model = new InspectionData
                {
                    Code = item.Code,
                    Id = YitIdHelper.NextId(),
                    InspectionName = item.InspectionName,
                    Remark = item.Remark,
                    InspectionScheme = inspectionScheme,
                    InspectionSchemeId = input.Id,
                    InspectionType = item.InspectionType,
                    NsTargetValue = item.NsTargetValue,
                    NsLowerLimit = item.NsLowerLimit,
                    NsUpperLimit = item.NsUpperLimit,
                    SjLowerLimit = item.SjLowerLimit,
                    SjTargetValue = item.SjTargetValue,
                    SjUpperLimit = item.SjUpperLimit,
                };
                items.Add(model);
            }
            await _inspectionDataRep.InsertAsync(items);
        }

        /// <summary>
        /// 获取试验项目枚举
        /// </summary>
        /// <returns></returns>
        [HttpGet("inspectionScheme/getInspectionType")]
        public async Task<List<SelectDto>> GetInspectionTypeEnum()
        {
            var list = new List<SelectDto>();

            var model = default(InspectionType);

            FieldInfo[] fieldinfo = typeof(InspectionType).GetFields();

            foreach (FieldInfo field in fieldinfo)
            {
                SelectDto enumModel = new SelectDto();
                if (!(Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute))
                {
                    enumModel.Label = field.GetValue(model).ToString();
                }
                else
                {
                    enumModel.Label = attribute.Description;
                }
                enumModel.Value = field.GetValue(model).GetHashCode();

                if (field.GetValue(model).ToString() != "0")
                {
                    list.Add(enumModel);
                }

            }
            return list;
        }

        /// <summary>
        /// 新增
        /// </summary>
        [HttpPost("inspectionScheme/add")]
        [UnitOfWork]
        public async Task Add(AddInspectionSchemeInput input)
        {
            var isExist = await _inspectionSchemeRep.DetachedEntities.AnyAsync(u => u.Code == input.Code || u.Name == input.Name);
            if (isExist)
                throw Oops.Oh("已存在相同名称与编号的试验方案！");

            if (string.IsNullOrWhiteSpace(input.Code))
            {
                input.Code = await _generateCodeUtilService.GenerateCode(BusinessType.InspectionScheme);
            }

            input.Id = YitIdHelper.NextId();

            var inspectionScheme = new InspectionScheme
            {
                Id = input.Id,
                Code = input.Code,
                Name = input.Name,
                Remark = input.Remark,
                ValidStatus = input.ValidStatus
            };
            await _inspectionSchemeRep.InsertNowAsync(inspectionScheme);

            //input.Adapt<InspectionScheme>();
            //inspectionScheme.InspectionDatas.Clear();
            if (input.InspectionDatas.Count > 0)
            {
                await UpdateInspectionSchemeData(input, inspectionScheme);
                //await _inspectionDataRep.InsertNowAsync(items);
            }

        }

        /// <summary>
        /// 删除
        /// </summary>
        [HttpPost("inspectionScheme/delete")]
        [UnitOfWork]
        public async Task Delete(long id)
        {
            var inspectionScheme = await _inspectionSchemeRep.FirstOrDefaultAsync(u => u.Id == id);
            if (inspectionScheme == null)
                throw Oops.Oh("不存在此数据！");

            var plans= await _experimentPlanRep.DetachedEntities.Where(s=>s.InspectionSchemeId== id).ToListAsync();

            if (plans.Count > 0)
            {
                throw Oops.Oh("已经有试验计划和此方案关联，请勿删除！");
            }

            await inspectionScheme.DeleteAsync();
            // 删配置试验项实体
            var inspectionDatas = await _inspectionDataRep.Where(u => u.InspectionSchemeId == inspectionScheme.Id).ToListAsync();
            await _inspectionDataRep.DeleteAsync(inspectionDatas);
        }

        /// <summary>
        /// 获取详细信息
        /// </summary>
        [HttpGet("inspectionScheme/detail")]
        public async Task<InspectionSchemeDetail> Detail(long id)
        {
            var inspectionScheme = await _inspectionSchemeRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == id);
            if (inspectionScheme == null)
                throw Oops.Oh("不存在此数据！");

            var inspectionDatas = await _inspectionDataRep.DetachedEntities.Where(u => u.InspectionSchemeId == inspectionScheme.Id).ToListAsync();

            var inspectionSchemeDetail = inspectionScheme.Adapt<InspectionSchemeDetail>();

            inspectionSchemeDetail.InspectionDatas = inspectionDatas;

            return inspectionSchemeDetail;
        }


        /// <summary>
        /// 获取详细信息
        /// </summary>
        [HttpGet("inspectionScheme/show")]
        public async Task<InspectionSchemeShowDetail> Show(long id)
        {
            var inspectionScheme = await _inspectionSchemeRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == id);
            if (inspectionScheme == null)
                throw Oops.Oh("不存在此数据！");

            var inspectionDatas = await _inspectionDataRep.DetachedEntities.Where(u => u.InspectionSchemeId == inspectionScheme.Id)
                .Select(s => new InspectionDataOutput
                {
                    Remark = s.Remark,
                    InspectionName = s.InspectionName,
                    InspectionType = s.InspectionType,
                    NsTargetValue = s.NsTargetValue,
                    NsUpperLimit = s.NsUpperLimit,
                    NsLowerLimit = s.NsLowerLimit,
                    SjTargetValue = s.SjTargetValue,
                    SjLowerLimit = s.SjLowerLimit,
                    SjUpperLimit = s.SjUpperLimit,
                }).ToListAsync();

            var inspectionSchemeDetail = inspectionScheme.Adapt<InspectionSchemeShowDetail>();

            inspectionSchemeDetail.InspectionDatas = inspectionDatas;

            return inspectionSchemeDetail;
        }


        /// <summary>
        /// 获取方案详细信息
        /// </summary>
        [HttpGet("inspectionScheme/getInspectionData")]
        public async Task<List<InspectionDataOutput>> GetInspectionData(long schemeId)
        {
            var inspectionDatas = await _inspectionDataRep.DetachedEntities.Where(u => u.InspectionSchemeId == schemeId)
                .Select(u => new InspectionDataOutput
                {
                    Id = u.Id,
                    Code = u.Code,
                    InspectionName = u.InspectionName,
                    Remark = u.Remark,
                    InspectionSchemeId = u.InspectionSchemeId,
                    InspectionType = u.InspectionType,
                    NsLowerLimit = u.NsLowerLimit,
                    SjLowerLimit = u.SjLowerLimit,
                    NsUpperLimit = u.NsUpperLimit,
                    SjTargetValue = u.SjTargetValue,
                    SjUpperLimit = u.SjUpperLimit,
                    NsTargetValue = u.NsTargetValue,
                })
                .ToListAsync();

            return inspectionDatas;
        }

        /// <summary>
        /// 编辑
        /// </summary>
        [HttpPost("inspectionScheme/edit")]
        [UnitOfWork]
        public async Task Edit(EditInspectionSchemeInput input)
        {
            var inspectionScheme = await _inspectionSchemeRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (inspectionScheme == null)
                throw Oops.Oh("不存在此数据！");

            var isExist = await _inspectionSchemeRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
            if (isExist)
                throw Oops.Oh("已存在相同名称与编号的试验方案！");

            inspectionScheme.Remark = input.Remark;
            inspectionScheme.ValidStatus = input.ValidStatus;
            inspectionScheme.Name = input.Name;
            await _inspectionSchemeRep.UpdateAsync(inspectionScheme);

            if (input.InspectionDatas.Count > 0)
            {
                await UpdateInspectionSchemeData(input, inspectionScheme);
            }
        }

        /// <summary>
        /// 下拉数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("inspectionScheme/selectList")]
        public async Task<List<SelectDto>> SelectList()
        {
            var list = await _inspectionSchemeRep.DetachedEntities.Where(s => s.ValidStatus).OrderBy(s => s.Sort).ToListAsync();
            return list.Select(x => new SelectDto
            {
                Value = x.Id,
                Label = $"{x.Code}-{x.Name}"
            }).ToList();
        }

        /// <summary>
        /// 分页数据
        /// </summary>
        [HttpGet("inspectionScheme/page")]
        public async Task<PageResult<InspectionSchemeOutput>> QueryPage([FromQuery] InspectionSchemePageInput input)
        {
            var name = !string.IsNullOrEmpty(input.SearchValue?.Trim());
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            var inspectionSchemes = await _inspectionSchemeRep.DetachedEntities
                                         .Where((name, u => u.Name.Contains(input.SearchValue.Trim())))
                                         .Where((code, u => u.Code.Contains(input.Code.Trim())))
                                         .Where(input.ValidStatus.HasValue, u => u.ValidStatus == input.ValidStatus)
                                         .OrderBy(u => u.Sort)
                                         .Select(u => new InspectionSchemeOutput
                                         {
                                             Id = u.Id,
                                             Code = u.Code,
                                             Name = u.Name,
                                             Remark = u.Remark,
                                             ValidStatus = u.ValidStatus,
                                             CreatedTime = u.CreatedTime,
                                             CreatedUserName = u.CreatedUserName,
                                             UpdatedTime = u.UpdatedTime,
                                             UpdatedUserName = u.UpdatedUserName,
                                             Sort = u.Sort,
                                         }).ToADPagedListAsync(input.PageNo, input.PageSize);

            return inspectionSchemes;
        }
    }
}
